package com.shallowUniverse.process.context.sql;

import com.shallowUniverse.process.configuration.ProcessProperties;
import com.shallowUniverse.process.utils.ProcessUtil;
import lombok.Data;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;


/**
 * @author gs
 * @date create in 2021/1/17 11:36
 */
@Data
public class SqlSentenceUtil {

    private ProcessProperties processProperties;
    private static Map<String, String> sqlFactory;

    public SqlSentenceUtil(ProcessProperties processProperties) {
        this.processProperties = processProperties;
        try {
            this.doParseSentence();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * description: 根据id获取sql <br/>
     * author: Shuai Guo   <br/>
     * date: 2021/7/14 <br/>
     * params: [id] <br/>
     * return: java.lang.String <br/>
     * version: 1.0
     */
    public static String generateSentence(String id) {
        return sqlFactory.get(id);
    }

    /**
     * description: 拼接条件 <br/>
     * author: Shuai Guo   <br/>
     * date: 2021/7/28 <br/>
     * params: [sqlId, object, entityFields, sqlFields, signs] <br/>
     * return: java.lang.String <br/>
     * version: 1.0
     */
    public static String generateSentenceWithFieldConditions(String sqlId, Object object, String[] entityFields, String[] sqlFields, String[] signs) {
        //通过sqlId拿到sql
        String sql = sqlFactory.get(sqlId);
        //判断对象是否为空
        if (ObjectUtils.isEmpty(object)) {
            return sql;
        }
        //判断是否有分组关键字
        StringBuilder[] sqlArray = new StringBuilder[2];
        if (sql.contains("group")) {
            sqlArray[0] = new StringBuilder(sql.substring(0, sql.indexOf("group")));
            sqlArray[1] = new StringBuilder(sql.substring(sql.indexOf("group")));
        } else if (sql.contains("order")) {
            sqlArray[0] = new StringBuilder(sql.substring(0, sql.indexOf("order")));
            sqlArray[1] = new StringBuilder(sql.substring(sql.indexOf("order")));
        } else {
            sqlArray[0] = new StringBuilder(sql);
            sqlArray[1] = new StringBuilder("");
        }
        //判断是否有where
        if (!sqlArray[0].toString().contains("where")) {
            sqlArray[0].append(" where 1=1");
        }
        //循环拼接条件
        for (int i = 0; i < entityFields.length; i++) {
            String field = entityFields[i];
            Object value = ProcessUtil.getFieldValue(object, field);
            if (!ObjectUtils.isEmpty(value)) {
                String sign = signs[i];
                String sqlField = sqlFields[i];
                if ("like".equals(sign)) {
                    sqlArray[0].append(" and ").append(sqlField).append(" ").append(sign).append(" '%").append(value.toString()).append("%'");
                } else {
                    //判断是否是字符串
                    if (value instanceof String) {
                        sqlArray[0].append(" and ").append(sqlField).append(sign).append("'").append(value.toString()).append("'");
                    } else {
                        sqlArray[0].append(" and ").append(sqlField).append(sign).append(value.toString());
                    }
                }
            }
        }
        return String.join(" ", sqlArray);
    }

    /**
     * description: 创建sql <br/>
     * author: gs   <br/>
     * date: 2021/3/16 <br/>
     * params: [] <br/>
     * return: void
     */
    private void doParseSentence() throws DocumentException {
        //获取读取对象
        SAXReader reader = new SAXReader();
        //根据读取对象生成文档对象
        Document document = reader.read(SqlSentenceUtil.class.getResourceAsStream("/jdbc/JdbcStore.xml"));
        //获取根节点
        Element rootElement = document.getRootElement();
        //获取所有子节电
        List<Element> elements = rootElement.elements();
        //初始化sql工厂
        sqlFactory = new HashMap<>(elements.size());
        elements.forEach(element -> {
            //获取sql的id
            Attribute attribute = element.attribute("id");
            String id = attribute.getValue();
            //获取原生sql
            String sql = element.getTextTrim();
            //获取所有条件
            List<Element> conditionList = element.elements("condition");
            List<String> conditions = new ArrayList<>();
            for (Element condition : conditionList) {
                //获取条件字段
                Attribute field = condition.attribute("field");
                //拆分
                String[] fields = field.getValue().split(",");
                //判断条件字段值是否为空
                if (validateCondition(fields)) {
                    Attribute value = condition.attribute("value");
                    conditions.add(value.getValue());
                } else {
                    conditions.add("");
                }
            }
            //判断条件集合是否为空
            if (!CollectionUtils.isEmpty(conditionList)) {
                sql = String.format(sql, conditions.toArray());
            }
            //添加sql
            sqlFactory.put(id, replacePlaceholder(sql));
        });
    }

    /**
     * description: 校验条件 <br/>
     * author: Shuai Guo   <br/>
     * date: 2021/7/26 <br/>
     * params: [fields] <br/>
     * return: boolean <br/>
     * version: 1.0
     */
    private boolean validateCondition(String[] fields) {
        AtomicBoolean flag = new AtomicBoolean(true);
        Arrays.stream(fields).forEach(field -> {
            try {
                if (ObjectUtils.isEmpty(FieldUtils.readField(processProperties, field, true))) {
                    flag.set(false);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        return flag.get();
    }

    /**
     * description: 替換占位符 <br/>
     * author: Shuai Guo   <br/>
     * date: 2021/7/14 <br/>
     * params: [content] <br/>
     * return: java.lang.String <br/>
     * version: 1.0
     */
    private String replacePlaceholder(String content) {
        return content
                .replaceAll("#database", processProperties.getDatabase())
                .replaceAll("#userTable", processProperties.getUserTable())
                .replaceAll("#roleTable", processProperties.getRoleTable())
                .replaceAll("#userId", processProperties.getUserId())
                .replaceAll("#roleId", processProperties.getRoleId())
                .replaceAll("#userRealName", processProperties.getUserRealName())
                .replaceAll("#roleName", processProperties.getRoleName())
                .replaceAll("#deptId", processProperties.getDeptId())
                .replaceAll("#deptName", processProperties.getDeptName())
                .replaceAll("#deptTable", processProperties.getDeptTable())
                .replaceAll("##", "%,").replaceAll("\\$\\$", ",%");
    }
}
